<template>
<div class="YUploadImg">
  <el-upload
    ref="yUpload"
    action=""
    :disabled="disabled"
    drag
    :file-list="picsList"
    :http-request="doUpload"
    :on-change="onChange"
    list-type="picture-card"
    accept="image/*"
    :limit="limit"
    :class="{'max-pic': maxPic}"
    :auto-upload="false" >
    <i slot="default" class="el-icon-plus"></i>
    <div slot="file" slot-scope="{file}">
      <img
        class="el-upload-list__item-thumbnail"
        :src="file.url" alt=""
      >
      <span class="el-upload-list__item-actions">
        <span
          class="el-upload-list__item-preview"
          @click="handlePictureCardPreview(file)"
        >
          <i class="el-icon-zoom-in"></i>
        </span>
        <template v-if="!disabled">
          <span
              v-if="reUpload"
              class="el-upload-list__item-delete"
              @click="handleEdit(file)"
          >
            <i class="el-icon-upload2"></i>
          </span>
          <span
              class="el-upload-list__item-delete"
              @click="handleRemove(file)"
          >
            <i class="el-icon-delete"></i>
          </span>
        </template>
      </span>
    </div>
  </el-upload>
  <el-upload
    ref="yUpload2"
    style="display: none"
    action=""
    :file-list="editParam.picsList"
    list-type="picture-card"
    :on-change="onChange2"
    :show-file-list="false"
    :http-request="doUpload"
    accept="image/*"
    :auto-upload="false">
    <el-button ref="editUpload"></el-button>
  </el-upload>
  <el-dialog
    :visible.sync="previewVisible"
    @closed="closePreview"
    append-to-body>
    <img width="100%" :src="dialogImageUrl" alt="">
  </el-dialog>
  <el-dialog
    :visible.sync="showCropper"
    title="图片剪裁"
    v-dialog-drag
    width="800px"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    :show-close="false"
    append-to-body>
    <div class="cropper-content">
      <div class="cropper" style="text-align:center">
        <vue-cropper
          ref="cropper"
          v-bind="myOptions"
        ></vue-cropper>
      </div>
    </div>
    <div slot="footer" class="dialog-footer">
      <el-button @click="cancelCropper">取消</el-button>
      <el-button type="primary" @click="finishCropper">确认</el-button>
    </div>
  </el-dialog>
</div>
</template>

<script>
import { VueCropper } from 'vue-cropper'
export default {
  name: "YUploadImg",
  components: { VueCropper  },
  inject: ['File2ArrayBuffer', 'generateMediaUrl'],
  props:{
    limit:{
      type: Number,
      default: Infinity
    },
    businessSysModuleCode: String,
    url:{},
    valueType: String,
    cropperOptions: Object,
    reUpload:{
      type: Boolean,
      default: false
    },
    disabled:{
      type: Boolean,
      default: false
    },
    redrawOnServer:{//是否在图片保存/删除走接口之后才重绘页面，默认为false
      type: Boolean,
      default: false
    }
  },
  computed:{
    maxPic(){
      return this.picsList.length >= this.limit || this.disabled;
    },
    urlType(){
      if(this.valueType) return this.valueType;
      if(Array.isArray(this.url)){
        return "Array";
      }else{
        return "String"
      }
    },
    myOptions(){
      return Object.assign({}, this.option, this.cropperOptions, this.cropperOptions || {})
    }
  },
  data(){
    return{
      cropperType: '',
      showCropper: false,
      picsList: [],
      fileInfo: null,
      option: {
        img: '', // 裁剪图片的地址
        info: true, // 裁剪框的大小信息
        outputSize: 1, // 裁剪生成图片的质量
        outputType: 'png', // 裁剪生成图片的格式
        canScale: true, // 图片是否允许滚轮缩放
        autoCrop: true, // 是否默认生成截图框
        autoCropWidth: 750, // 默认生成截图框宽度
        autoCropHeight: 600, // 默认生成截图框高度
        fixedBox: false, // 固定截图框大小 不允许改变
        fixed: true, // 是否开启截图框宽高固定比例
        fixedNumber: [3, 2], // 截图框的宽高比例
        full: true, // 是否输出原图比例的截图
        canMoveBox: true, // 截图框能否拖动
        original: false, // 上传图片按照原始比例渲染
        centerBox: true, // 截图框是否被限制在图片里面
        infoTrue: true // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
      },
      previewVisible: false,
      dialogImageUrl: '',
      updateLock: false,
      editParam:{
        picsList: [],
        currentFile: null
      }
    }
  },
  methods:{
    resetUrl(){
      this.$set(this, 'picsList', []);
      if(this.url){
        if(this.urlType === 'Array' || this.urlType === 'ObjectArray'){
          this.url.map(u => {
            if(this.urlType === 'Array' || this.urlType === 'ObjectArray'){
              this.picsList.push({
                url: this.generateMediaUrl({
                  fileOpenUrl: u.url || u.imgUrl || u
                }),
                name: u.url || u.imgUrl || u,
                id: u.id
              });
            }else{
              this.picsList.push({
                url: this.generateMediaUrl({
                  fileOpenUrl: u
                }),
                name: u
              });
            }
          })
        }else{
          this.picsList.push({
            url: this.generateMediaUrl({
              fileOpenUrl: this.url
            }),
            name: this.url
          });
        }
      }
    },
    getEmitData(){
      switch(this.urlType){
        case "String":{
          return this.picsList.length ? this.picsList[0].name : '';
        }
        case "Array":{
          return this.picsList.map(p => p.name);
        }
        case "ObjectArray":{
          return this.picsList;
        }
      }
    },
    doUpload(){

    },
    handlePictureCardPreview(file){
      this.dialogImageUrl = file.url;
      this.previewVisible = true;
    },
    closePreview(){
      this.dialogImageUrl = '';
    },
    // 上传按钮   限制图片大小
    onChange(file, fileList) {
      if(file.status === 'ready'){//选择完成
        if(!file.raw.type.startsWith('image/')){
          this.$message({
            type: 'warning',
            message: '只允许上传图片'
          });
          this.$refs['yUpload'].clearFiles();
          return false;
        }
        /*const isLt5M = file.size / 1024 / 1024 < 5
        if (!isLt5M) {
          this.$message.error('上传文件大小不能超过 5MB!')
          return false
        }*/
        this.fileInfo = file;
        // 上传成功后将图片地址赋值给裁剪框显示图片
        this.$nextTick(() => {
          this.option.img = file.url
          this.cropperType = 'add'
          this.showCropper = true
        })
      }
    },
    onChange2(file){
      if(file.status === 'ready'){
        if(!file.raw.type.startsWith('image/')){
          this.$message({
            type: 'warning',
            message: '只允许上传图片'
          });
          this.$refs['yUpload2'].clearFiles();
          return false;
        }
        this.fileInfo = file;
        this.$nextTick(() => {
          this.option.img = file.url
          this.cropperType = 'edit'
          this.showCropper = true
        })
      }
    },
    handleEdit(file){
      this.editParam.currentFile = file;
      //let obj = this.picsList.find(f => f.name)
      this.$refs['editUpload'].$el.click();
    },
    handleRemove(file, fileList){
      let delFile = {...file};
      let delIndex = this.picsList.findIndex(f => f.uid === file.uid);
      let delId = this.picsList[delIndex].uid;
      // this.$delete(this.picsList, delIndex);
      if(this.redrawOnServer){
        this.$nextTick(() => {
          this.$bus.$once('redraw', bool => {
            bool && delIndex >= 0 && this.$delete(this.picsList, delIndex);
          })
        })
      }else{
        delIndex >= 0 && this.$delete(this.picsList, delIndex);
      }
      delId && this.$yAxios({
        url: this.$api.common.removeAttachment,
        data:{
          id: delId
        },
      }, info => {
        console.log(info,'sc')
        if(info){
          this.updateLock = true;
          this.$emit("update:url", this.getEmitData());
          this.$nextTick(() => {
            this.$emit("update", {
              type: 'delete',
              file: delFile
            });
          })
        }else{
          this.$nextTick(() => {
            this.$emit("update", {
              type: 'delete',
              file: delFile
            });
          })
        }
      })
    },
    cancelCropper(){
      this.$set(this, 'picsList', [...this.picsList]);
      this.showCropper = false;
    },
    // 点击裁剪，这一步是可以拿到处理后的地址
    finishCropper() {
      this.$refs.cropper.getCropBlob(async (blob) => {
        let buffer = await this.File2ArrayBuffer(blob);
        let md5 = this.$MD5(buffer);
        let file = new File(
          [blob],
            md5 + '.' + this.myOptions.outputType,
          {type: blob.type}
        );
        let fileSize = file.size;
        //文件上传
        let formData = new FormData()
        formData.append('businessSysModuleCode', this.businessSysModuleCode);
        formData.append('file', file);
        formData.append('businessSysCode', businessSysCode);
        formData.append('fileSize', fileSize);
        formData.append('md5', md5);
        this.$yAxios({
          url: this.$api.common.upload,
          data: formData,
          loading: true
        }, ({data}) => {
          const param = Object.gain(data, [
            'businessId','businessSysCode','businessSysModuleCode','id:fileId','fileName','fileId:fileOpenUrl'
          ]);
          param.fileType = blob.type;
          param.fileOperQx = '0';
          this.$yAxios({
            url: this.$api.common.saveAttachment,
            data: param,
            loading: true
          }, info => {
            let newImg = {
              id: info.id,
              uid: this.fileInfo.uid,
              name: info.fileOpenUrl,
              url: this.generateMediaUrl(info)
            }, oldFile;
            oldFile = {...this.editParam.currentFile}
            if(this.redrawOnServer){
              if(this.cropperType === 'add'){
                this.picsList.push(newImg);
              }else{
                Object.assign(this.editParam.currentFile, newImg);
              }
              // this.$nextTick(() => {
              //   this.$bus.$once('redraw', bool => {
              //     console.log(this.cropperType,6666,bool)
              //     if(bool){
              //       if(this.cropperType === 'add'){
              //         this.picsList.push(newImg);
              //       }else{
              //         Object.assign(this.editParam.currentFile, newImg);
              //       }
              //     }
              //   })
              // })
            }else{
              if(this.cropperType === 'add'){
                this.picsList.push(newImg);
              }else{
                Object.assign(this.editParam.currentFile, newImg);
              }
            }
            this.updateLock = true;
            this.$emit("update:url", this.getEmitData());
            this.$nextTick(() => {
              let args = {
                type: this.cropperType,
                file: newImg
              }
              if(this.cropperType === 'edit'){
                args.preFile = oldFile;
              }
              this.$emit("update", args);
              //这里手动gc一下
              this.$set(this.editParam, 'picsList', []);
            })
          }, e => {
            this.$set(this, 'picsList', [...this.picsList]);
          })
          this.showCropper = false;
        }, e => {
          this.$set(this, 'picsList', [...this.picsList]);
        })
      })
    }
  },
  watch:{
    url:{
      handler(newVal, oldVal){
        if(this.updateLock) this.updateLock = false;
        else{
          JSON.stringify(newVal) !== JSON.stringify(oldVal) && this.resetUrl();
        }
      },
      immediate: true
    }
  }
}
</script>

<style scoped lang="less">
.YUploadImg{
  display: inline-block;
  /*width: 148px;*/
  min-height: 148px;
  /deep/.el-upload{
    .el-upload-dragger{
      width: 100%;
      height: 100%;
    }
  }
  /deep/.el-upload-list__item{
    margin: 0;
    transition: none!important;
  }
  /deep/.max-pic{
    .el-upload{
      display: none;
    }
  }
}

// 截图
.cropper-content {
  .cropper {
    width: auto;
    height: 300px;
  }
}
</style>
